<?
/**
 * Copyright 2007 Melange.
 *
 * This file is part of PHP-MELANGE.
 *
 * PHP-MELANGE is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * PHP-MELANGE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PHP-MELANGE; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category    Melange
 * @package     php-melange
 * @subpackage  cms
 * @copyright   Copyright (c) 2007 Jeroen Simons. All rights reserved
 * @author      Jeroen Simons <jeroen@melange.nl>
 * @link        http://www.melange.nl/
 *
 */
 
class PHP_CMS_View_Helper_TruncateNicely {


    /**
     * Truncates a string nicely. It will search for the first space
     * after the lower limit and truncate the string there.  It will
     * also append any string passed as a parameter to the end of the
     * string.  The hard limit can be specified to forcibily truncate a
     * string (in the case of an extremely long word or such).  All
     * HTML/XML markup will be stripped from the string prior to
     * processing for truncation.
     *
     * @param str         String the string to be truncated.
     * @param lower       int value of the lower limit.
     * @param upper       int value of the upper limit, -1 if no limit is
     *                    desired. If the uppper limit is lower than the
     *                    lower limit, it will be adjusted to be same as
     *                    the lower limit.
     * @param appendToEnd String to be appended to the end of the
     *                    truncated string.
     *                    This is appended ONLY if the string was indeed
     *                    truncated. The append is does not count towards
     *                    any lower/upper limits.
     *
     * @author timster@mac.com
     */
    public function truncateNicely($str, $lower, $upper, $appendToEnd="")
    {
        // strip markup from the string
        $str = strip_tags($str);

        // unescape temporarily for length handling
        $str = self::unescapeXml($str);

        // quickly adjust the upper if it is set lower than 'lower'
        if($upper < $lower) {
            $upper = $lower;
        }

        // now determine if the string fits within the upper limit
        // if it does, go straight to return, do not pass 'go' and collect $200
        if(strlen($str) > $upper) {

            // the magic location int
            $loc;

            // first we determine where the next space appears after lower
            $loc = strpos($str, ' ', $lower);

            // now we'll see if the location is greater than the lower limit
            if($loc !== false && $loc >= $lower) {
                // yes it was, so we'll cut it off here
                $str = substr($str, 0, $loc);
            } else {
                // no it wasnt, so we'll cut it off at the upper limit
                $str = substr($str, 0, $upper);
            }

            // the string was truncated, so we append the appendToEnd String
            $str = $str . $appendToEnd;
        }

        // escape after finished processing string
        $str = self::escapeXml($str);

        return $str;
    }

    private static function escapeXml($str) {
        $str = str_replace("&","&amp;", $str);
        $str = str_replace("<","&lt;", $str);
        $str = str_replace(">","&gt;", $str);
        $str = str_replace("\"","&quot;", $str);
        $str = str_replace("'","&apos;", $str);
        return $str;
    }

    private static function unescapeXml($str) {
        $str = str_replace("&amp;","&", $str);
        $str = str_replace("&lt;","<", $str);
        $str = str_replace("&gt;",">", $str);
        $str = str_replace("&quot;","\"", $str);
        $str = str_replace("&apos;","'", $str);
        return $str;
    }

}
?>
